security(data-plane): canonical percent-decode, raw header limits, admin exposure warning#97
Merged
Merged
Conversation
…min exposure warning Addresses the data-plane hardening items (area 3, issue #9). - DP-4: replace the per-byte `byte as char` query decoder (which corrupted multi-byte UTF-8, e.g. %C3%A9) with one canonical UTF-8-correct `percent_decode`, and apply it to captured path-parameter values too — so routing, validation, and dispatch all agree on the decoded value. Path segments are still matched raw, so `%2F` stays a literal slash within its segment rather than acting as a separator. - DP-5: enforce header limits on the raw HeaderMap. `HeaderMap::len()` counts every header line, so duplicate names can no longer undercount the header limit, and each value is size-checked (not just the last for a given name). - DP-8: the unauthenticated admin port (/health, /metrics, /provenance) now logs a startup warning when bound to a non-loopback address, since /provenance and /metrics expose build/operational metadata. Documented. Also updates the validation integration test to expect 413 (payload-too-large) for oversized bodies, matching the RFC-correct status introduced in PR #94. AR rebinding residual (pin the vetted IP via a custom DNS resolver to close the resolve-then-connect TOCTOU) is deferred: it is a cross-cutting refactor of the WASM HTTP client's DNS path. Left tracked in #9.
This was referenced Jul 2, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Area 3 — data-plane misc (#9)
Final area of the sequential security pass.
DP-4 — percent-decode / path confusion
The query decoder built each
%XXbyte viabyte as char, which corrupts multi-byte UTF-8 (e.g.%C3%A9→ two garbage chars instead ofé), skewing validation. Replaced with a single canonical, UTF-8-correctpercent_decode(byte buffer +from_utf8_lossy), and applied it to captured path-parameter values too — so routing, validation, and dispatch all see the same decoded value. Path segments are still matched raw, so%2Fremains a literal slash within its segment rather than acting as a separator (no encoded-slash confusion introduced).DP-5 — header-count dedup
Header limits were enforced on a
HashMapthat collapses duplicate names, so repeated headers undercounted the limit and only the last value for a name was size-checked. Limits are now enforced on the rawHeaderMap(len()counts every line; each value size-checked) before the map is built for downstream use.DP-8 — admin exposure
/health,/metrics,/provenanceare unauthenticated by design (scraping), but/provenanceand/metricsleak build/operational metadata. The admin server now logs a startup warning when bound to a non-loopback address, and the behavior is documented.Deferred
AR rebinding residual (resolve-then-connect TOCTOU: reqwest re-resolves at connect, so a rebinding attacker could still reach an internal IP): closing it properly means moving the SSRF check into a custom DNS resolver for the WASM HTTP client — a cross-cutting refactor. Kept tracked in #9.
Verification
percent_decodeUTF-8 correctness + malformed-escape passthrough; raw header count/size limits.routingandvalidation(updated one stale assertion to the RFC-correct 413 for oversized bodies, from PR security(data-plane): ingress DoS hardening + chunked body-size cap #94) and the full security suite (21 passed / 4 ignored).Resolves the data-plane items tracked in #9 (minus the deferred rebinding residual).